package com.group9.handinhand.controller;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ValidationUtils;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import com.group9.handinhand.controller.form.ProfileViewForm;
import com.group9.handinhand.controller.form.UserUpdateForm;
import com.group9.handinhand.controller.form.UserWallViewForm;
import com.group9.handinhand.service.CommunityService;
import com.group9.handinhand.service.TagService;
import com.group9.handinhand.service.UserService;
import com.group9.handinhand.service.so.CommunitySO;
import com.group9.handinhand.service.so.FriendshipRequestSO;
import com.group9.handinhand.service.so.FriendshipSO;
import com.group9.handinhand.service.so.TagSO;
import com.group9.handinhand.service.so.UserSO;
import com.group9.handinhand.service.so.UserTagSO;
import com.group9.handinhand.utils.SemanticSearch;
/**
 * a controller for User
 *
 */
@Controller
public class UserController extends AbstractBaseController implements HttpRequestHandler {
	
	@Autowired
	UserService userService;
	
	@Autowired
	TagService tagService;
	
	@Autowired
	CommunityService communityService;
	
	private byte[] picture;
	/**
	 * a controller for view profile
	 * @param userId
	 * @param profileViewForm
	 * @param request
	 * @param response
	 * @param model
	 * @return
	 * @throws IOException 
	 * @throws ServletException 
	 */
	@RequestMapping(value = "/user/{userId}")
	public String viewProfile(@PathVariable Long userId, ProfileViewForm profileViewForm ,HttpServletRequest request, HttpServletResponse response,  Model model) throws ServletException, IOException {
		
		UserSO user = userService.getUserById(userId);
		List<UserTagSO> userTags = tagService.getUserTagsByUser(user);
		List<CommunitySO> communityList = communityService.getCommunitiesByUser(user);
		FriendshipSO friendship = userService.getFriendship(getUser().getId(), userId);
		FriendshipRequestSO friendshipRequest = userService.getFriendshipRequest(getUser().getId(), userId);
		profileViewForm.setProfileOwner(user);
		profileViewForm.setProfileViewer(getUser());
		profileViewForm.setProfileOwnerTags(userTags);
		profileViewForm.setCommunityList(communityList);
		profileViewForm.setFriendship(friendship);
		profileViewForm.setFriendshipRequest(friendshipRequest);
		
		return "viewProfile";
	}
	/**
	 * a controller for user wall
	 * @param request
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/userWall")
	public String userWall(HttpServletRequest request, Model model){
		
		UserSO user = getUser();
		if(user == null){
			return "redirect:";
		}
		UserWallViewForm userWallViewForm = new UserWallViewForm();
		userWallViewForm.setUserWallElements();
		ArrayList<Object> userWallElements = userWallViewForm.getUserWallElements();
		model.addAttribute("userWallElements", userWallElements);
		return "userWall";
	}
	/**
	 * a controller for editing profile
	 * @param userUpdateForm
	 * @param errors
	 * @param request
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/editProfile")
	public String editProfile(UserUpdateForm userUpdateForm ,BindingResult errors, HttpServletRequest request, Model model){
		UserSO user = getUser();
		if(user != null) {
			userUpdateForm.setUser(user);
			List<TagSO> selectedTags = tagService.getTagsByRelatedUserId(user.getId());
			userUpdateForm.setSelectedTagsFromList(selectedTags);
			picture = user.getPicture();
		}
		return "updateProfile";
	}
	/**
	 * a controller for updating user
	 * @param userUpdateForm
	 * @param errors
	 * @param request
	 * @param response
	 * @param model
	 * @param file
	 * @return
	 */
	@RequestMapping(value = "/updateUser", method = RequestMethod.POST)
	public String updateUser(UserUpdateForm userUpdateForm, BindingResult errors, HttpServletRequest request, HttpServletResponse response,  Model model,
			 @RequestParam(value = "file", required = false) MultipartFile file)  {	
		
		UserSO user = userUpdateForm.getUser();
		UserSO oldUser = userService.getUserByUsername(getUser().getUsername());
		user.setId(oldUser.getId());
		user.setPassword(oldUser.getPassword());
		user.setSocialUsers(oldUser.getSocialUsers());
		
		validateUser(userUpdateForm, errors, file);
		
		if(errors.hasErrors()) {
			return editProfile(userUpdateForm, errors, request, model);
		}
		userService.updateUser(user);
		List<String> selectedTags = userUpdateForm.getSelectedTagsAsList();
		
		tagService.saveUserTags(user,selectedTags);
		
		authenticateUserAndSetSession(user, request);		
				
		return "redirect:/";
	}
	/**
	 * a method for validating user
	 * @param userUpdateForm
	 * @param errors
	 * @param file
	 */
	private void validateUser(UserUpdateForm userUpdateForm, BindingResult errors, MultipartFile file) {
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "user.username", "required.field");
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "user.name", "required.field");
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "user.surname", "required.field");
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "user.email", "required.field");
		
		UserSO user = userUpdateForm.getUser();
		
		UserSO userExists = userService.getUserByEmail(user.getEmail());
		if(userExists != null && userExists.getId() != user.getId()) {
			errors.rejectValue("user.email", "email.alreadyregistered");
		}
		if(userUpdateForm.getPassword() != null && !userUpdateForm.getPassword().equals("")) {
			if(!userUpdateForm.getPassword().equals(userUpdateForm.getRePassword())){
				errors.rejectValue("rePassword", "passwords.dontmatch");
				errors.rejectValue("user.password", "","");
			}
			else
				userUpdateForm.getUser().setPassword(userUpdateForm.getPassword());
		}
		if (!file.isEmpty()) {
			String pictureName = file.getName();
			try {
				byte[] bytes = file.getBytes();
				user.setPicture(bytes);

			} catch (Exception e) {
				System.out.println("Upload picture failed" + pictureName
						+ e.getMessage());
				errors.rejectValue("file", "");
			}
		}else{
			try {
				user.setPicture(picture);

			} catch (Exception e) {
				System.out.println("Upload picture failed" + e.getMessage());
				errors.rejectValue("file", "");
			}
		}
	}
	/**
	 * a controller for adding friend
	 * @param userId
	 * @param request
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/addFriend/{userId}")
	public String addFriend(@PathVariable Long userId ,HttpServletRequest request, Model model ) {
		
		UserSO user = getUser();
		
		if(user != null) {
			userService.saveFriendshipRequest(user.getId(), userId);	
		}
		
		return "redirect:/user/" + userId;
	}
	/**
	 * a controller for view people list
	 * @param request
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/people")
	public String people(HttpServletRequest request, Model model ) {
		ArrayList<FriendshipRequestSO> friendshipRequestList = new ArrayList<FriendshipRequestSO>();
		ArrayList<FriendshipSO> friendshipList = new ArrayList<FriendshipSO>();
		UserSO user = getUser();	
		if(user != null) {
			friendshipRequestList = userService.getFriendshipRequests(user.getId());
			friendshipList = userService.getFriendships(user.getId());
		}
		model.addAttribute("friendshipRequestList", friendshipRequestList);
		model.addAttribute("friendshipList", friendshipList);
		model.addAttribute("userId", user.getId());
		return "viewPeople";
	}
	
	/**
	 * a controller for accepting friendship request
	 * @param userId
	 * @param request
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/acceptFriendship/{userId}")
	public String acceptFriendship(@PathVariable Long userId ,HttpServletRequest request, Model model ) {
		
		UserSO user = getUser();
		
		if(user != null) {
			FriendshipSO friendship = userService.saveFriendship(user.getId(), userId);	
			if(friendship != null) {
				userService.deleteFriendshipRequest(userId, user.getId());
			}
		}
		
		return "redirect:/user/" + userId;
	}
	/**
	 * a controller for canceling friendship request
	 * @param userId
	 * @param request
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/cancelFriendshipRequest/{userId}")
	public String cancelFriendshipRequest(@PathVariable Long userId ,HttpServletRequest request, Model model ) {
		
		UserSO user = getUser();
		
		if(user != null) {
			userService.deleteFriendshipRequest(user.getId(), userId);	
		}
		
		return "redirect:/user/" + userId;
	}
	/**
	 * a controller for rejecting friendship
	 * @param userId
	 * @param request
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/rejectFriendship/{userId}")
	public String rejectFriendship(@PathVariable Long userId ,HttpServletRequest request, Model model ) {
		
		UserSO user = getUser();
		
		if(user != null) {
			userService.deleteFriendshipRequest(userId, user.getId());	
		}
		
		return "redirect:/user/" + userId;
	}
	/**
	 * a controller for unfriending
	 * @param userId
	 * @param request
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/unfriend/{userId}")
	public String unfriend(@PathVariable Long userId ,HttpServletRequest request, Model model ) {
		
		UserSO user = getUser();
		
		if(user != null) {
			userService.deleteFriendship(userId, user.getId());	
		}
		
		return "redirect:/user/" + userId;
	}

	@RequestMapping(value = "/picture")
	public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	       
	        byte[] thumb = getUser().getPicture();

	        response.setContentType("image/jpeg, image/jpg, image/png, image/gif");
	        response.getOutputStream().write(thumb);


	        response.getOutputStream().close();

	}
	
	@RequestMapping(value = "/deletePicture/{userId}")
	public String deletePicture(@PathVariable Long userId, HttpServletRequest request, HttpServletResponse response){
	       
		UserSO user = getUser();
		user.setPicture(null);
		userService.deletePicture(user);
			
		return "redirect:/editProfile";
	}

}
